package com.kexio.file.service.impl;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kexio.common.exception.BusinessException;
import com.kexio.file.entity.StorageObject;
import com.kexio.file.mapper.StorageObjectMapper;
import com.kexio.file.service.StorageObjectService;
import com.kexio.file.storage.StorageManager;
import com.kexio.file.storage.StorageResult;
import com.kexio.file.util.FileHashUtils;
import com.kexio.file.vo.StorageObjectVO;

/**
 * 存储对象服务实现类
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class StorageObjectServiceImpl extends ServiceImpl<StorageObjectMapper, StorageObject> implements StorageObjectService {
    
    private static final Logger log = LoggerFactory.getLogger(StorageObjectServiceImpl.class);
    
    @Autowired
    private StorageObjectMapper storageObjectMapper;
    
    @Autowired
    private StorageManager storageManager;
    
    @Override
    public StorageObject getById(String id) {
        return baseMapper.selectById(id);
    }
    
    @Override
    public StorageObject createOrGetStorageObject(InputStream inputStream, long contentLength, 
                                                  String contentType, String storageType, 
                                                  String bucketName, Map<String, String> metadata) {
        try {
            // 计算文件哈希值
            java.io.BufferedInputStream bufferedStream = new java.io.BufferedInputStream(inputStream);
            bufferedStream.mark(Integer.MAX_VALUE);
            
            FileHashUtils.FileHashResult hashResult = FileHashUtils.calculateHash(bufferedStream);
            bufferedStream.reset();
            
            // 检查是否已存在相同内容的存储对象
            StorageObject existingObject = getByContentHash(hashResult.getSha256());
            if (existingObject != null) {
                log.info("发现重复存储对象，增加引用计数: storageObjectId={}, hash={}", 
                        existingObject.getId(), hashResult.getSha256());
                incrementReferenceCount(existingObject.getId(), 1);
                return existingObject;
            }
            
            // 生成存储路径
            String objectKey = FileHashUtils.generateStorageKey("", hashResult.getSha256());
            
            // 存储文件到存储后端
            StorageResult storageResult = storageManager.storeFile(
                    storageType, bucketName, objectKey, bufferedStream, 
                    contentLength, contentType, metadata);
            
            if (!storageResult.isSuccess()) {
                throw new BusinessException("文件存储失败: " + storageResult.getErrorMessage());
            }
            
            // 创建存储对象记录
            StorageObject storageObject = new StorageObject();
            storageObject.setContentHash(hashResult.getSha256());
            storageObject.setFileSize(hashResult.getFileSize());
            storageObject.setStorageType(storageManager.getProvider(storageType).getStorageType());
            storageObject.setBucketName(storageResult.getBucketName());
            storageObject.setStoragePath(storageResult.getObjectKey());
            storageObject.setStorageUrl(storageResult.getStorageUrl());
            storageObject.setReferenceCount(1);
            storageObject.setStatus(1); // 已存储
            storageObject.setStorageTime(LocalDateTime.now());
            storageObject.setVerifyStatus(0); // 未验证
            
            // 保存到数据库
            save(storageObject);
            
            log.info("存储对象创建成功: storageObjectId={}, hash={}, size={}", 
                    storageObject.getId(), hashResult.getSha256(), hashResult.getFileSize());
            
            return storageObject;
            
        } catch (Exception e) {
            log.error("创建存储对象失败", e);
            throw new BusinessException("创建存储对象失败: " + e.getMessage());
        }
    }
    
    @Override
    public StorageObject findOrCreateByContentHash(String contentHash, InputStream inputStream, 
                                                   long contentLength, String contentType, 
                                                   String storageType, String bucketName, 
                                                   Map<String, String> metadata) {
        // 先查找现有的存储对象
        StorageObject existingObject = getByContentHash(contentHash);
        if (existingObject != null) {
            incrementReferenceCount(existingObject.getId(), 1);
            return existingObject;
        }
        
        // 不存在则创建新的存储对象
        return createOrGetStorageObject(inputStream, contentLength, contentType, storageType, bucketName, metadata);
    }
    
    @Override
    public StorageObject getByContentHash(String contentHash) {
        return storageObjectMapper.selectByContentHash(contentHash, null);
    }
    
    @Override
    public StorageObjectVO getVOById(String storageObjectId) {
        StorageObject storageObject = getById(storageObjectId);
        if (storageObject == null) {
            return null;
        }
        
        return convertToVO(storageObject);
    }
    
    @Override
    public StorageObject updateStorageObject(String storageObjectId, StorageObject storageObject) {
        StorageObject existing = getById(storageObjectId);
        if (existing == null) {
            throw new BusinessException("存储对象不存在");
        }
        
        // 只允许更新部分字段
        existing.setStorageUrl(storageObject.getStorageUrl());
        existing.setVerifyStatus(storageObject.getVerifyStatus());
        existing.setStorageMetadata(storageObject.getStorageMetadata());
        
        updateById(existing);
        return existing;
    }
    
    @Override
    public boolean deleteStorageObject(String storageObjectId) {
        StorageObject storageObject = getById(storageObjectId);
        if (storageObject == null) {
            return false;
        }
        
        // 检查引用计数
        if (storageObject.getReferenceCount() != null && storageObject.getReferenceCount() > 0) {
            throw new BusinessException("存储对象仍有引用，不能删除");
        }
        
        // 从存储后端删除文件
        boolean deleted = storageManager.deleteFile(
                storageObject.getStorageType(),
                storageObject.getBucketName(),
                storageObject.getStoragePath()
        );
        
        if (deleted) {
            // 从数据库删除记录
            removeById(storageObjectId);
            log.info("存储对象删除成功: storageObjectId={}", storageObjectId);
        }
        
        return deleted;
    }
    
    @Override
    public int incrementReferenceCount(String storageObjectId, Integer increment) {
        if (increment == null || increment <= 0) {
            increment = 1;
        }
        
        storageObjectMapper.incrementReferenceCount(storageObjectId, increment);
        
        // 返回更新后的引用计数
        StorageObject storageObject = getById(storageObjectId);
        return storageObject != null ? storageObject.getReferenceCount() : 0;
    }
    
    @Override
    public int decrementReferenceCount(String storageObjectId, Integer decrement) {
        if (decrement == null || decrement <= 0) {
            decrement = 1;
        }
        
        storageObjectMapper.decrementReferenceCount(storageObjectId, decrement);
        
        // 返回更新后的引用计数
        StorageObject storageObject = getById(storageObjectId);
        return storageObject != null ? storageObject.getReferenceCount() : 0;
    }
    
    @Override
    public int getReferenceCount(String storageObjectId) {
        StorageObject storageObject = getById(storageObjectId);
        return storageObject != null ? storageObject.getReferenceCount() : 0;
    }
    
    // ==================== 其他方法的简化实现 ====================
    
    @Override
    public IPage<StorageObjectVO> listStorageObjects(long current, long size, String storageType, 
                                                     String storageConfig, Integer status) {
        // TODO: 实现分页查询
        return null;
    }
    
    @Override
    public IPage<StorageObjectVO> listByStorageType(String storageType, long current, long size) {
        // TODO: 实现按存储类型查询
        return null;
    }
    
    @Override
    public List<StorageObject> listCleanableObjects(Integer limit) {
        return storageObjectMapper.selectCleanableObjects(null, limit);
    }
    
    @Override
    public Long countByStorageType(String storageType) {
        return storageObjectMapper.countByStorageType(storageType, null);
    }
    
    @Override
    public Long sumSizeByStorageType(String storageType) {
        return storageObjectMapper.sumSizeByStorageType(storageType, null);
    }
    
    @Override
    public Long calculateSpaceSaved() {
        return storageObjectMapper.calculateSpaceSaved(null);
    }
    
    @Override
    public Map<String, Object> getStorageStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalObjects", count());
        stats.put("spaceSaved", calculateSpaceSaved());
        // TODO: 添加更多统计信息
        return stats;
    }
    
    @Override
    public boolean verifyStorageObjectIntegrity(String storageObjectId) {
        StorageObject storageObject = getById(storageObjectId);
        if (storageObject == null) {
            return false;
        }
        
        boolean result = storageManager.verifyFileIntegrity(
                storageObject.getStorageType(),
                storageObject.getBucketName(),
                storageObject.getStoragePath(),
                storageObject.getContentHash()
        );
        
        // 更新验证状态
        updateVerifyStatus(storageObjectId, result ? 1 : 2);
        
        return result;
    }
    
    @Override
    public Map<String, Boolean> batchVerifyIntegrity(List<String> storageObjectIds) {
        Map<String, Boolean> results = new HashMap<>();
        for (String id : storageObjectIds) {
            results.put(id, verifyStorageObjectIntegrity(id));
        }
        return results;
    }
    
    @Override
    public List<StorageObject> listObjectsNeedVerify(LocalDateTime lastVerifyBefore, Integer limit) {
        return storageObjectMapper.selectObjectsNeedVerify(lastVerifyBefore, null, limit);
    }
    
    @Override
    public boolean updateVerifyStatus(String storageObjectId, Integer verifyStatus) {
        int result = storageObjectMapper.updateVerifyStatus(storageObjectId, verifyStatus, LocalDateTime.now());
        return result > 0;
    }
    
    @Override
    public int cleanupUnreferencedObjects(int batchSize) {
        List<StorageObject> cleanableObjects = listCleanableObjects(batchSize);
        int count = 0;
        
        for (StorageObject obj : cleanableObjects) {
            try {
                if (deleteStorageObject(obj.getId())) {
                    count++;
                }
            } catch (Exception e) {
                log.warn("清理存储对象失败: storageObjectId={}", obj.getId(), e);
            }
        }
        
        return count;
    }
    
    @Override
    public int repairReferenceCount(String storageObjectId) {
        // TODO: 实现引用计数修复逻辑
        return 0;
    }
    
    @Override
    public int batchUpdateStatus(List<String> storageObjectIds, Integer status) {
        return storageObjectMapper.batchUpdateStatus(storageObjectIds, status, "system");
    }
    
    @Override
    public boolean migrateStorageObject(String storageObjectId, String targetStorageType, String targetBucket) {
        // TODO: 实现存储对象迁移逻辑
        return false;
    }
    
    @Override
    public StorageObject copyStorageObject(String sourceStorageObjectId, String targetStorageType, String targetBucket) {
        // TODO: 实现存储对象复制逻辑
        return null;
    }
    
    @Override
    public Map<String, Object> calculateUsageInfo(String storageObjectId) {
        // TODO: 实现使用情况计算
        return new HashMap<>();
    }
    
    // ==================== 私有方法 ====================
    
    /**
     * 转换为VO对象
     */
    private StorageObjectVO convertToVO(StorageObject storageObject) {
        StorageObjectVO vo = new StorageObjectVO();
        vo.setId(storageObject.getId());
        vo.setContentHash(storageObject.getContentHash());
        vo.setFileSize(storageObject.getFileSize());
        vo.setHumanReadableSize(getHumanReadableSize(storageObject.getFileSize()));
        vo.setStorageType(storageObject.getStorageType());
        vo.setBucketName(storageObject.getBucketName());
        vo.setStoragePath(storageObject.getStoragePath());
        vo.setStorageConfig(storageObject.getStorageConfig());
        vo.setReferenceCount(storageObject.getReferenceCount());
        vo.setStatus(storageObject.getStatus());
        vo.setStatusText(getStatusText(storageObject.getStatus()));
        vo.setIsEncrypted(storageObject.getIsEncrypted());
        vo.setEncryptionAlgorithm(storageObject.getEncryptionAlgorithm());
        vo.setCompressionAlgorithm(storageObject.getCompressionAlgorithm());
        vo.setOriginalSize(storageObject.getOriginalSize());
        vo.setCompressionRatio(storageObject.getCompressionRatio());
        vo.setStorageTime(storageObject.getStorageTime());
        vo.setLastVerifyTime(storageObject.getLastVerifyTime());
        vo.setVerifyStatus(storageObject.getVerifyStatus());
        vo.setVerifyStatusText(getVerifyStatusText(storageObject.getVerifyStatus()));
        vo.setCreateTime(storageObject.getCreateTime());
        vo.setUpdateTime(storageObject.getUpdateTime());
        
        return vo;
    }
    
    /**
     * 获取状态文本
     */
    private String getStatusText(Integer status) {
        if (status == null) return "未知";
        switch (status) {
            case 0: return "存储中";
            case 1: return "已存储";
            case 2: return "存储失败";
            case 3: return "已删除";
            default: return "未知";
        }
    }
    
    /**
     * 获取验证状态文本
     */
    private String getVerifyStatusText(Integer verifyStatus) {
        if (verifyStatus == null) return "未验证";
        switch (verifyStatus) {
            case 0: return "未验证";
            case 1: return "验证通过";
            case 2: return "验证失败";
            default: return "未知";
        }
    }
    
    /**
     * 获取文件大小的人类可读格式
     */
    private String getHumanReadableSize(Long fileSize) {
        if (fileSize == null || fileSize <= 0) {
            return "0 B";
        }
        
        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double size = fileSize.doubleValue();
        
        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }
        
        return String.format("%.1f %s", size, units[unitIndex]);
    }
}
